package com.spa.application.service.admin;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.spa.application.command.admin.MassagistWithdrawPayCommand;
import com.spa.application.command.admin.ShopWithdrawAuditCommand;
import com.spa.application.command.admin.ShopWithdrawPayCommand;
import com.spa.application.config.massagist.ProfitRule;
import com.spa.application.dto.PageResult;
import com.spa.application.dto.admin.*;
import com.spa.application.dto.admin.AdminWithdrawOrderDetailDTO;
import com.spa.application.dto.admin.ShopWithdrawOrderListDTO;
import com.spa.application.dto.admin.OrderProfitInfo;
import com.spa.application.query.admin.*;
import com.spa.domain.entity.*;
import com.spa.domain.service.*;
import com.spa.infrastructure.enums.dict.profit.OrderProfitType;
import com.spa.infrastructure.enums.dict.profit.OrderType;
import com.spa.infrastructure.enums.withdraw.WithdrawStatusEnum;
import com.spa.infrastructure.exception.SpaException;
import com.spa.infrastructure.mapper.MassagistWithdrawRecordMapperStruct;
import com.spa.infrastructure.mapper.OrderMapperStruct;
import com.spa.infrastructure.mapper.ShopWithdrawRecordMapperStruct;
import com.spa.infrastructure.repository.condition.OrderInfoCondition;
import com.spa.infrastructure.util.SessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
@Slf4j
public class AdminWithdrawApplicationService {

    @Autowired
    private ShopWithdrawRecordService shopWithdrawRecordService;

    @Autowired
    private MassagistWithdrawRecordService massagistWithdrawRecordService;

    @Autowired
    private SysAdminUserService sysAdminUserService;

    @Resource
    private OrderService orderService;

    @Resource
    private ProfitService profitService;

    public void payForMassagist(MassagistWithdrawPayCommand command) {
        MassagistWithdrawRecord massagistWithdrawRecord = massagistWithdrawRecordService.getDetailById(command.getWithdrawId());
        if (ObjectUtil.equal(massagistWithdrawRecord.getStatus(),WithdrawStatusEnum.$10.getCode())) {
            throw new SpaException("当前状态不能打款！");
        }
        massagistWithdrawRecordService.payForMassagist(command);
    }

    public PageResult<ShopWithdrawList4AdminDTO> shopPage(ShopWithdrawListQuery query) {
        Page<ShopWithdrawRecord> page = shopWithdrawRecordService.page(ShopWithdrawRecordMapperStruct.INSTANCE.query2Condition(query));
        return ShopWithdrawRecordMapperStruct.INSTANCE.entity2ShopWithdrawList4AdminDto4Page(page);
    }

    public PageResult<MessagistWithdrawList4AdminDTO> massagistPage(MessagistWithdrawListQuery query) {
        Page<MassagistWithdrawRecord> page = massagistWithdrawRecordService.page(MassagistWithdrawRecordMapperStruct.INSTANCE.query2Condition(query));
        return MassagistWithdrawRecordMapperStruct.INSTANCE.entity2MessagistWithdrawList4AdminDto4Page(page);
    }

    public void audit(ShopWithdrawAuditCommand command) {
        ShopWithdrawRecord shopWithdrawRecord = shopWithdrawRecordService.getDetailById(command.getWithdrawId());
        if (shopWithdrawRecord.getStatus() != WithdrawStatusEnum.$10.getCode()) {
            throw new SpaException("当前状态不能审核！");
        }
        long userId = SessionUtil.getUser().getExtUserId();
        SysUserEntity sysUser = sysAdminUserService.infoById(userId);
        shopWithdrawRecordService.adminAudit(command.getWithdrawId(), userId, sysUser.getUserName());
    }

    public void payForShop(ShopWithdrawPayCommand command) {
        ShopWithdrawRecord shopWithdrawRecord = shopWithdrawRecordService.getDetailById(command.getWithdrawId());
        if (shopWithdrawRecord.getStatus() == WithdrawStatusEnum.$10.getCode()) {
            throw new SpaException("当前状态不能打款！");
        }
        shopWithdrawRecordService.payForShop(command);
    }

    public List<MessagistWithdrawExportDTO> massagisList(MessagistWithdrawListQuery query) {
        return MassagistWithdrawRecordMapperStruct.INSTANCE.entity2MessagistWithdrawExportDto4List(massagistWithdrawRecordService.list(MassagistWithdrawRecordMapperStruct.INSTANCE.query2Condition(query)));
    }

    public List<ShopWithdrawExportDTO> shopWithdrawList(ShopWithdrawListQuery query) {
        return ShopWithdrawRecordMapperStruct.INSTANCE.entity2ShopWithdrawExportDto4List(shopWithdrawRecordService.list(ShopWithdrawRecordMapperStruct.INSTANCE.query2Condition(query)));
    }


    /**
     * 技师提现记录订单分页列表
     * @param query
     * @return
     */
    public PageResult<MassagistOrderListWithdrawDTO> MassagistWithdrawOrderList(MassagistWithdrawRecordDetailQuery query) {
        OrderInfoCondition condition = MassagistWithdrawRecordMapperStruct.INSTANCE.massagistWithdrawRecordDetailQuery2Condition(query);
        OrderService.OrderInfoPlug plug = OrderService.OrderInfoPlug.empty();
        plug.setProfit(true);
        Page<OrderInfo> orderInfoPage = orderService.pageByCondition(condition, plug);
        // 计算每笔订单的分佣合计
        List<OrderProfitInfo> orderProfitInfoList = calculateOrderProfit(orderInfoPage.getRecords());
        PageResult<MassagistOrderListWithdrawDTO> result = OrderMapperStruct.INSTANCE.entity2MassagistOrderListWithdrawDto4Page(orderInfoPage);
        result.getRecords().forEach(orderListWithdrawDTO -> {
            OrderProfitInfo orderProfitInfo = orderProfitInfoList.stream().filter(item -> item.getOrderId().equals(orderListWithdrawDTO.getId())).findFirst().orElse(null);
            if (orderProfitInfo!=null){
                orderListWithdrawDTO.setMassagistIncome(orderProfitInfo.getMassagistIncome());
                orderListWithdrawDTO.setTravelPrice(orderProfitInfo.getTravelPrice());
                orderListWithdrawDTO.setAmount(orderListWithdrawDTO.getMassagistIncome()+orderListWithdrawDTO.getTravelPrice());
            }
        });
        return result;
    }

    /**
     * 门店提现记录查看对应订单分页列表
     * @param query
     * @return
     */
    public PageResult<ShopWithdrawOrderListDTO> ShopWithdrawOrderList(ShopWithdrawRecordDetailOrderListQuery query) {
        OrderInfoCondition condition = new OrderInfoCondition();
        condition.setShopWithdrawId(query.getShopWithdrawId());
        OrderService.OrderInfoPlug plug = OrderService.OrderInfoPlug.empty();
        plug.setProfit(true);
        Page<OrderInfo> orderInfoPage = orderService.pageByCondition(condition, plug);
        // 计算每笔订单的分佣合计
        List<OrderProfitInfo> orderProfitInfoList = calculateOrderProfit(orderInfoPage.getRecords());
        PageResult<ShopWithdrawOrderListDTO> result = OrderMapperStruct.INSTANCE.entity2AdminShopWithdrawOrderListDTO4Page(orderInfoPage);
        result.getRecords().forEach(orderListWithdrawDTO -> {
            OrderProfitInfo orderProfitInfo = orderProfitInfoList.stream().filter(item -> item.getOrderId().equals(orderListWithdrawDTO.getId())).findFirst().orElse(null);
            if (orderProfitInfo!=null){
                orderListWithdrawDTO.setAmount(orderProfitInfo.getShopIncome());
            }
        });
        return result;
    }

    /**
     * 提现订单详情
     * @param query
     * @return
     */
    public AdminWithdrawOrderDetailDTO orderDetail(AdminWithdrawOrderDetailQuery query) {
        OrderService.OrderInfoPlug plug = OrderService.OrderInfoPlug.empty();
        plug.setOrderExt(true);
        plug.setProfit(true);
        plug.setTicket(true);
        OrderInfo orderInfo = orderService.getOrderInfoById(query.getOrderId(), plug);
        if (ObjectUtil.isNull(orderInfo)){
            throw new SpaException("订单查询失败！");
        }
        // 计算每笔订单的分佣合计
        List<OrderProfitInfo> orderProfitInfoList = calculateOrderProfit(Collections.singletonList(orderInfo));
        AdminWithdrawOrderDetailDTO adminWithdrawOrderDetailDTO = OrderMapperStruct.INSTANCE.entity2AdminWithdrawOrderDetailDTO(orderInfo);
        OrderProfitInfo orderProfitInfo = orderProfitInfoList.stream().filter(item -> item.getOrderId().equals(orderInfo.getId())).findFirst().orElse(null);
        if (orderProfitInfo!=null){
            if (Objects.equals(query.getType(), OrderProfitType.$2.getCode())){
                adminWithdrawOrderDetailDTO.setTotalIncome(orderProfitInfo.getShopIncome());
            }else{
                adminWithdrawOrderDetailDTO.setTotalIncome(orderProfitInfo.getMassagistIncome()+orderProfitInfo.getTravelPrice());
            }
        }
        // 利润数据里面的提成比例拿出来
        List<Profit> profitList = orderInfo.getProfitList();
        // 订单分佣金额和比例
        List<OrderProfitRateInfo> orderProfitRateInfoList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(profitList)){
            profitList.forEach(profit -> {
                String ruleData = profit.getRuleData();
                if (ruleData!=null){
                    ProfitRule profitRule = JSONUtil.toBean(profit.getRuleData(), ProfitRule.class);
                    OrderProfitRateInfo orderProfitRateInfo =  new OrderProfitRateInfo();
                    orderProfitRateInfo.setOrderId(profit.getOrderId());
                    orderProfitRateInfo.setOrderType(profit.getOrderType());
                    if (Objects.equals(query.getType(), OrderProfitType.$2.getCode())){
                        orderProfitRateInfo.setIncome(profit.getShopIncome());
                        orderProfitRateInfo.setRate(Convert.toDouble(profitRule.getShopRule(), 0D));
                    }else{
                        orderProfitRateInfo.setIncome(profit.getMassagistIncome());
                        orderProfitRateInfo.setRate(Convert.toDouble(profitRule.getMassagistPercent(), 0D));
                    }
                    if (Objects.equals(profit.getOrderType(), OrderType.$1.getCode()) || Objects.equals(profit.getOrderType(), OrderType.$3.getCode())){
                        orderProfitRateInfo.setOrderId(profit.getOrderId());
                    }else if (Objects.equals(profit.getOrderType(), OrderType.$2.getCode()) && profit.getExtendOrderId()!=null){
                        orderProfitRateInfo.setOrderId(profit.getExtendOrderId());
                    }
                    orderProfitRateInfoList.add(orderProfitRateInfo);
                }
            });
        }
        // 订单分佣金额、分佣比例赋值
        OrderProfitRateInfo orderProfitRateInfo = orderProfitRateInfoList.stream().filter(item->item.getOrderId().equals(orderInfo.getId()) && item.getOrderType() ==1).findFirst().orElse(null);
        adminWithdrawOrderDetailDTO.setPercent(orderProfitRateInfo!=null?orderProfitRateInfo.getRate():null);
        adminWithdrawOrderDetailDTO.setIncome(orderProfitRateInfo!=null? (float) orderProfitRateInfo.getIncome() :null);
        // 加钟订单分佣比例赋值
        List<AdminWithdrawOrderDetailDTO.Ext> extList = adminWithdrawOrderDetailDTO.getExtList();
        if (extList!=null){
            extList.forEach(ext -> {
                OrderProfitRateInfo orderProfitRateInfoExt = orderProfitRateInfoList.stream().filter(item->item.getOrderId().equals(ext.getId()) && item.getOrderType() ==2).findFirst().orElse(null);
                if (orderProfitRateInfoExt==null){
                    orderProfitRateInfoExt = orderProfitRateInfoList.stream().filter(item->item.getOrderId().equals(ext.getOrderId()) && item.getOrderType() ==2).findFirst().orElse(null);
                }
                if (orderProfitRateInfoExt!=null){
                    ext.setPercent(orderProfitRateInfoExt.getRate());
                    ext.setIncome((float)orderProfitRateInfoExt.getIncome());
                }
            });
        }
        return adminWithdrawOrderDetailDTO;
    }

    /**
     * 计算每笔订单的分佣合计
     *
     * @param orderInfos
     * @return
     */
    private List<OrderProfitInfo> calculateOrderProfit(List<OrderInfo> orderInfos) {
        List<OrderProfitInfo> profitInfoList = new ArrayList<>();
        for (OrderInfo orderInfo : orderInfos) {
            int massagistIncome = 0;
            int travelPrice = 0;
            int shopIncome = 0;
            if (orderInfo.getProfitList() != null) {
                massagistIncome = orderInfo.getProfitList().stream()
                        .mapToInt(profit -> profit.getMassagistIncome() != null ? profit.getMassagistIncome() : 0)
                        .sum();

                travelPrice = orderInfo.getProfitList().stream()
                        .mapToInt(profit -> profit.getTravelPrice() != null ? profit.getTravelPrice() : 0)
                        .sum();

                shopIncome = orderInfo.getProfitList().stream()
                        .mapToInt(profit -> profit.getShopIncome() != null ? profit.getShopIncome() : 0)
                        .sum();
            }
            OrderProfitInfo orderProfitInfo = new OrderProfitInfo(orderInfo.getId(), massagistIncome, travelPrice, shopIncome);
            profitInfoList.add(orderProfitInfo);
        }
        return profitInfoList;
    }
}
